#include "RobotController.h"
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonArray>
#include <QCoreApplication>
#include <QHash>
#include <QDir>
#include "SCHeadData.h"
#include "../global_logger.h"

const QHash<int, QString> RobotController::stateMap = {
    {0, "NONE"},
    {2, "RUNNING"},
    {3, "SUSPENDED"},
    {4, "COMPLETED"},
    {5, "FAILED"},
    {6, "CANCELED"}
};

RobotController::RobotController(QObject *parent) : QObject(parent) {
    m_worker = new StatusWorker(5000);   // 5秒间隔查询一次控制权状态
    m_worker->moveToThread(&m_workerThread);

    // 连接工作线程信号到主线程槽函数
    //connect(m_worker, &StatusWorker::requestBattery, this, &RobotController::getRobotBattery);
    //connect(m_worker, &StatusWorker::requestPosition, this, &RobotController::getRobotPosition);
    connect(m_worker, &StatusWorker::requestNavState, this, &RobotController::getRobotNavigationalState);
    connect(m_worker,&StatusWorker::requestControlAuthority,this,&RobotController::getControlAuthority);    //查询控制权
    connect(m_worker,&StatusWorker::requestRobotAlarmStatus,this,&RobotController::getRobotAlarmStatus);    //查询机器人报警状态

    m_workerThread.start(); // 内部自动调用 exec() 
    LOG_INFO("RobotController 初始化完成,状态轮询工作线程已启动.");
}

void RobotController::connectRobot(const QString &seerIP, const QString &robotIP) {
    LOG_INFO("尝试连接机器人控制器 - seerIP: {} robotIP:{} ", seerIP.toStdString(),robotIP.toStdString());
    m_ctrlSocket.connectHost(seerIP, SEER_API_PORT_CTRL);
    m_naviSocket.connectHost(seerIP, SEER_API_PORT_NAVI);
    m_statSocket.connectHost(seerIP, SEER_API_PORT_STAT);
    m_otherSocket.connectHost(seerIP, SEER_API_PORT_OTHER);
    m_confSocket.connectHost(seerIP, SEER_API_PORT_CONF);
    m_logsSocket.connectHost(robotIP, RMS_CLIENT_LOG_DOWNLOAD_PORT); //自定义日志下载Socket

    // 使用内部 socket 连接信号
    connect(m_statSocket.tcpSocket(), &QTcpSocket::connected, [this]() {
        LOG_INFO("SRC控制器连接成功");
        // 连接成功后自动获取当前地图
        getCurrentMap();
    });
    
    // 添加断开连接的处理
    connect(m_statSocket.tcpSocket(), &QTcpSocket::disconnected, [this]() {
         LOG_INFO("机器人控制器断开连接");
        // 停止状态轮询
        if (m_worker) {
            m_worker->stop();
            LOG_DEBUG("状态轮询已停止");
        };
    });
    
    connect(m_statSocket.tcpSocket(), QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred),
        [this](QAbstractSocket::SocketError error) {
           LOG_ERROR("机器人控制器Socket错误: {}", static_cast<int>(error));
            // 停止状态轮询
            if (m_worker) {
                m_worker->stop();
            }
        });
    m_worker->start();
    LOG_DEBUG("机器人连接初始化完成;轮询控制权状态定时器启动。");
}

RobotController::~RobotController() {
    // 在线程退出前停止定时器
    if (m_worker) {
        m_worker->stop();
        LOG_DEBUG("状态轮询已停止");
    }
    
    // 断开所有连接
    disconnect(m_worker, nullptr, this, nullptr);
    
    // 退出并等待线程结束
    m_workerThread.quit();
    m_workerThread.wait();
    LOG_DEBUG("工作线程已退出");
    // 删除worker对象
    if (m_worker) {
        m_worker->deleteLater(); // 改为 deleteLater 确保线程安全
        m_worker = nullptr;
    }
}

void RobotController::disconnectRobot() {
    // 停止定时器
    if (m_worker) {
        m_worker->stop();
    }

    m_ctrlSocket.releaseTcpSocket();
    m_naviSocket.releaseTcpSocket();
    m_statSocket.releaseTcpSocket();
    m_otherSocket.releaseTcpSocket();
    m_confSocket.releaseTcpSocket();
    m_logsSocket.releaseTcpSocket();
    
    QMutexLocker locker(&m_dataMutex);
    m_battery = -1.0;
    m_position = PositionData{}; // 结构体清零
    m_navState.clear();
    m_currentTarget.clear();
    emit batteryUpdated(-1); // 通知UI重置状态
    LOG_INFO("机器人控制器盒子断开成功");
}

bool RobotController::isConnected() const {
    bool connected = m_statSocket.tcpSocket()->state() == QAbstractSocket::ConnectedState;
    LOG_DEBUG("检查连接状态: {}", connected ? "已连接" : "未连接");
    return connected;
}

// 自动重定位
void RobotController::relocation(const int cmdId) {
    LOG_INFO("执行重定位操作 - 命令: {}", cmdId);
    QJsonObject obj;
    obj["isAuto"] = true;
    QJsonDocument doc(obj);
    QByteArray json = doc.toJson(QJsonDocument::Compact);

    m_requestManager.sendRequest(&m_ctrlSocket, CMD_CTRL_RELOCATION, json, 
        [this](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            if(success){
                emit robotStatus("自动重定位成功!");
            }else{
                emit robotStatus("自动重定位失败!");
            }
            LOG_DEBUG("重定位操作完成 - 结果: {}", success ? "成功" : "失败");
        }
    );
}

void RobotController::runGoal(const QString &start, const QString &end)
{
    LOG_INFO("执行路径规划任务 - 起点: {}, 终点: {}", 
                       start.toStdString(), end.toStdString());
        
    // TODO: 实际发送路径规划指令
    Q_UNUSED(start);
    Q_UNUSED(end);
}

/**
 * @brief 获取机器人电池信息
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求获取机器人的电池状态信息。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送获取电池信息的命令，并通过回调函数处理响应结果。
 */
void RobotController::getRobotBattery(int cmdId){
    // 检查连接状态
    if (!isConnected()) {
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 发送获取电池信息请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 获取机器人位置信息
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求获取机器人的当前位置信息。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送获取位置信息的命令，并通过回调函数处理响应结果。
 */
void RobotController::getRobotPosition(int cmdId){
    // 检查连接状态
    if (!isConnected()) {
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 发送获取位置信息请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 获取机器人导航状态信息
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求获取机器人的导航状态信息。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送获取导航状态信息的命令，并通过回调函数处理响应结果。
 */
void RobotController::getRobotNavigationalState(int cmdId){
    // 检查连接状态
    if (!isConnected()) {
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 发送获取导航状态信息请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 处理机器人操作完成的回调函数
 * 
 * 该函数用于处理来自机器人设备的操作完成事件。根据命令ID解析返回的数据，
 * 更新内部状态并发出相应的信号通知外部观察者。
 * 
 * @param cmdId 命令ID，标识完成的操作类型
 * @param success 操作是否成功执行的标志
 * @param data 返回的数据内容，通常为JSON格式
 */
void RobotController::handleOperationCompleted(int cmdId, bool success, const QByteArray& data) {
    LOG_DEBUG("处理操作完成回调 - 命令ID: {}, 成功: {}", cmdId, success);
    
    if (!success) {
        LOG_WARN("操作失败 - 命令ID: {}", cmdId);
        return;
    }

    QMutexLocker locker(&m_dataMutex); // 加锁保护共享数据
    
    // 解析并缓存数据
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        LOG_ERROR("JSON解析错误: {}", parseError.errorString().toStdString());
        return;
    }
    locker.unlock();
    
    switch (cmdId) {
        case CMD_STATE_GET_BATTERY: {
            double newBattery = doc.object()["battery_level"].toDouble();
            //LOG_INFO("电池状态更新 - 电量: {}%", newBattery);
            if (!qFuzzyCompare(newBattery, m_battery)) {
                m_battery = newBattery;
                emit batteryUpdated(newBattery); // 独立信号
                LOG_DEBUG("电池电量更新 - 新电量: {}%", newBattery);
            }
            break;
        }
        case CMD_STATE_GET_POSITION: {
            QJsonObject posObj = doc.object();
            double x = posObj["x"].toDouble();
            double y = posObj["y"].toDouble();
            double angle = posObj["angle"].toDouble();
            //LOG_INFO("位置更新 - 坐标: ({}, {}), 角度: {}", x, y, angle);
            if (!qFuzzyCompare(x, m_position.x) || 
                !qFuzzyCompare(y, m_position.y)) {
                m_position = {x, y, angle};
                emit positionUpdated(x, y, angle); // 独立信号
                LOG_DEBUG("机器人位置更新 - 新位置: ({}, {}), 角度: {}", x, y, angle);
            }
            break;
        }
        case CMD_STATE_GET_NAVIGATIONAL_STATE: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["task_status"].toInt();
            QString newState = stateMap.value(taskStatus, "UNKNOWN");
            QString newTarget = jsonObj["target_id"].toString();

            //LOG_INFO("导航状态更新 - 状态: {}, 目标: {}", newState.toStdString(), newTarget.toStdString());

            // 直接更新状态并上报，不进行判断
            m_navState = newState;
            m_currentTarget = newTarget;
            emit navigationStateUpdated(newState, newTarget);
            LOG_DEBUG("导航状态更新完成 - 状态: {}, 目标: {}", 
                                newState.toStdString(), newTarget.toStdString());
            break;
        }
        case CMD_CTRL_SOFT_EMERGENCY_STOP: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();
        
            LOG_DEBUG("软急停命令执行完成 - 状态: {}", taskStatus);
            break;
        }
        case CMD_NAV_MOVE: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();

            LOG_DEBUG("平动命令执行完成 - 状态: {}", taskStatus);
            break;
        }
        case CMD_NAV_ROTATE: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();

            LOG_DEBUG("转动命令执行完成 - 状态: {}", taskStatus);
            break;
        }
        case CMD_NAV_FIXED_PATH: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();

            LOG_DEBUG("固定路径导航命令接收完成 - 状态: {}", taskStatus);
            break;
        }
        case CMD_CLEAR_ROBOT_ALARM: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();
            LOG_DEBUG("清除机器人所有报错命令执行完成 - 状态: {}", taskStatus);
            break;
        }
        case CMD_MAP_SITE_INFORMATION: {
            QJsonObject jsonObj = doc.object();
            int taskStatus = jsonObj["ret_code"].toInt();
            if(taskStatus == 0){
                // 只提取stations数组并发送，简化QML端的解析
                QJsonArray stationsArray = jsonObj["stations"].toArray();
                QJsonObject simplifiedData;
                simplifiedData["stations"] = stationsArray;

                QJsonDocument outputDoc(simplifiedData);
                QString stationData = QString::fromUtf8(outputDoc.toJson(QJsonDocument::Compact));
                emit mapStationInformationUpdated(stationData);

                // 添加调试日志
                //LOG_DEBUG("发送站点信息: {}", stationData.toStdString());
            }
            break;
        }
        case CMD_STATE_GET_ALARM_STATUS: {          //查询机器人报警状态
            QJsonObject jsonObj = doc.object();
            int retCode = jsonObj["ret_code"].toInt();

            // 解析报警状态信息
            QJsonArray errors = jsonObj["errors"].toArray();
            QJsonArray warnings = jsonObj["warnings"].toArray();
            QJsonArray fatals = jsonObj["fatals"].toArray();
            QJsonArray notices = jsonObj["notices"].toArray();

            // 构建完整的JSON对象并转换为字符串
            QJsonObject statusObj;
            statusObj["ret_code"] = retCode;
            statusObj["errors"] = errors;
            statusObj["warnings"] = warnings;
            statusObj["fatals"] = fatals;
            statusObj["notices"] = notices;

            QJsonDocument doc(statusObj);
            QString statusJson = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));

            // 发出报警状态更新信号，发送完整的JSON数据
            emit robotAlarmStatusUpdated(statusJson);

            LOG_DEBUG("机器人报警状态更新 - {}", statusJson.toStdString());
            break;
        }
        case CMD_GET_PATH_BETWEEN_TWO_POINT: {
            QJsonObject jsonObj = doc.object();
            int retCode = jsonObj["ret_code"].toInt();
            
            if(retCode == 0){
                // 提取地图列表数组并发送
                QJsonArray mapListArray = jsonObj["list"].toArray();
                QJsonObject simplifiedData;
                simplifiedData["list"] = mapListArray;

                QJsonDocument outputDoc(simplifiedData);
                QString mapListData = QString::fromUtf8(outputDoc.toJson(QJsonDocument::Compact));
                emit robotPathBetweenTwoPointUpdated(mapListData);

                LOG_DEBUG("发送地图列表: {}", mapListData.toStdString());
            }
            break;
        }
        default: {
            LOG_WARN("未知命令ID: {}", cmdId);
            break;
        }
    }
}

/**
 * @brief 设置机器人控制器的参数
 * @param robotId 机器人唯一标识符
 * @return 无返回值
 */
void RobotController::setParameters(const QString robotId){
    m_robotId = robotId;
    LOG_DEBUG("设置机器人参数 - 机器人ID: {}", robotId.toStdString());
}

/**
 * @brief 获取当前加载的地图名称
 */
void RobotController::getCurrentMap() {    
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("获取当前地图失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }
        
    // 发送获取当前地图请求
    m_requestManager.sendRequest(&m_statSocket, CMD_MAP_GET_CURRENT, QByteArray(),
        [this](const QByteArray &resp) {
            if (resp.isEmpty()) {
                LOG_WARN("获取当前地图失败: 响应数据为空");
                return;
            }
            
            QJsonParseError parseError;
            QJsonDocument doc = QJsonDocument::fromJson(resp, &parseError);
            if (parseError.error != QJsonParseError::NoError) {
                LOG_ERROR("解析当前地图响应失败: {}", parseError.errorString().toStdString());
                return;
            }

            QString currentMap = doc.object()["current_map"].toString();
            LOG_DEBUG("获取到当前地图名称: {}", currentMap.toStdString());
            
            if (!currentMap.isEmpty() && m_currentMapName != currentMap) {
                m_currentMapName = currentMap;
                LOG_INFO("当前地图更新为: {}", currentMap.toStdString());
            }
            
            if (!currentMap.isEmpty()) {
                // 检查本地是否存在该地图
                QString mapFileName = currentMap;
                if (!mapFileName.endsWith(".smap")) {
                    mapFileName += ".smap";
                }
                QString mapFilePath = QString("data/%1/map/%2").arg(m_robotId, mapFileName);
                QFile mapFile(mapFilePath);

                if (!mapFile.exists()) {
                    LOG_INFO("地图文件不存在，开始下载 - 地图: {}, 路径: {}", 
                                    currentMap.toStdString(), mapFilePath.toStdString());
                    downloadMap(currentMap);
                } else {
                    LOG_DEBUG("地图文件已存在 - 地图: {}", currentMap.toStdString());
                }
            } else {
                LOG_WARN("获取到的当前地图名称为空");
            }
        }
    );
}

/**
 * @brief 下载指定地图
 * @param mapName 地图名称
 */
void RobotController::downloadMap(const QString& mapName) {
    LOG_INFO("开始下载地图 - 地图名称: {}", mapName.toStdString());
    
    // 创建地图目录
    QString mapDirPath = QString("data/%1/map").arg(m_robotId);
    QDir mapDir(mapDirPath);
    if (!mapDir.exists()) {
        if (mapDir.mkpath(".")) {
            LOG_DEBUG("创建地图目录成功 - 路径: {}", mapDirPath.toStdString());
        } else {
            LOG_WARN("创建地图目录失败 - 路径: {}", mapDirPath.toStdString());
        }
    }
        
    // 构造请求JSON
    QJsonObject obj;
    obj["map_name"] = mapName;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 发送下载地图请求
    m_requestManager.sendRequest(&m_confSocket, CMD_MAP_DOWNLOAD, jsonData,
        [this, mapName, mapDirPath](const QByteArray &resp) {
            if (resp.isEmpty()) {
                LOG_WARN("地图下载失败 - 地图名称: {}, 响应数据为空", mapName.toStdString());
                return;
            }

            // 保存地图数据到文件，添加.smap后缀
            QString mapFileName = mapName;
            if (!mapFileName.endsWith(".smap")) {
                mapFileName += ".smap";
            }
            QString mapFilePath = QString("%1/%2").arg(mapDirPath, mapFileName);
            QFile mapFile(mapFilePath);
            if (mapFile.open(QIODevice::WriteOnly)) {
                qint64 bytesWritten = mapFile.write(resp);
                mapFile.close();
                if (bytesWritten == resp.size()) {
                    LOG_INFO("地图下载成功 - 地图: {}, 文件路径: {}, 大小: {} 字节", 
                                       mapName.toStdString(), mapFilePath.toStdString(), bytesWritten);
                } else {
                    LOG_ERROR("地图文件写入不完整 - 地图: {}, 期望写入: {} 字节, 实际写入: {} 字节", 
                                        mapName.toStdString(), resp.size(), bytesWritten);
                }
            } else {
                LOG_ERROR("保存地图文件失败 - 文件路径: {}, 错误信息: {}", 
                                    mapFilePath.toStdString(), mapFile.errorString().toStdString());
            }
        }
    );
}

/**
 * @brief 执行软急停操作
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求执行机器人的软急停操作。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送急停命令，并通过回调函数处理响应结果。
 */
void RobotController::softEmergencyStop(int cmdId, bool status) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("软急停操作失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 构造请求JSON
    QJsonObject obj;
    obj["status"] = status;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
    // 记录日志
    LOG_INFO("执行软急停操作 - 命令ID: {}, 状态: {}", cmdId, status ? "急停" : "恢复");
    
    // 发送软急停请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_otherSocket, cmdId, jsonData,
        [this, cmdId, status](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("软急停操作完成 - 命令ID: {}, 状态: {}, 结果: {}", cmdId, status ? "急停" : "恢复", success ? "成功" : "失败");
            if (status) {
                // 急停操作
                if (success) {
                    emit robotStatus("急停成功");
                } else {
                    emit robotStatus("急停失败");
                }
            } else {
                // 急停释放操作
                if (success) {
                    emit robotStatus("急停释放成功");
                } else {
                    emit robotStatus("急停释放失败");
                }
            }
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 控制机器人平动移动
 * @param dist 移动距离
 * @param vx X轴速度
 * @param vy Y轴速度
 * @param mode 移动模式
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求控制机器人的平动移动。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送移动命令，并通过回调函数处理响应结果。
 */
void RobotController::moveRobot(double dist, double vx, double vy, int mode, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人移动控制失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 构造请求JSON
    QJsonObject obj;
    obj["dist"] = dist;
    obj["vx"] = vx;
    //obj["vy"] = vy;
    obj["mode"] = mode;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 记录日志
    LOG_INFO("执行机器人移动控制 - 命令ID: {}, 距离: {}, Vx: {}, Vy: {}, 模式: {}",
                       cmdId, dist, vx, vy, mode);

    // 发送移动控制请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("机器人移动控制完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 控制机器人转动
 * @param angle 转动角度
 * @param vw 角速度
 * @param mode 转动模式
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求控制机器人的转动。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送转动命令，并通过回调函数处理响应结果。
 */
void RobotController::rotateRobot(double angle, double vw, int mode, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人转动控制失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 构造请求JSON
    QJsonObject obj;
    obj["angle"] = angle;
    obj["vw"] = vw;
    obj["mode"] = mode;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 记录日志
    LOG_INFO("执行机器人转动控制 - 命令ID: {}, 角度: {}, 角速度: {}, 模式: {}",
                       cmdId, angle, vw, mode);

    // 发送转动控制请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("机器人转动控制完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 查询控制权状态
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求查询机器人的控制权状态。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送查询控制权命令，并通过回调函数处理响应结果。
 * 如果返回信息中locked为false，则代表控制权为自己所有；
 * 如果locked为true，则代表控制权属于其他客户端，需要抢占控制权。
 */
void RobotController::getControlAuthority(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("查询控制权失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行查询控制权操作 - 命令ID: {}", cmdId);

    // 发送查询控制权请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("查询控制权完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");

            if (success) {
                // 解析响应数据
                QJsonParseError parseError;
                QJsonDocument doc = QJsonDocument::fromJson(resp, &parseError);
                if (parseError.error != QJsonParseError::NoError) {
                    LOG_ERROR("解析控制权响应失败: {}", parseError.errorString().toStdString());
                    emit controlAuthorityUpdated(false, ""); // 发出控制权状态信号
                    return;
                }

                QJsonObject jsonObj = doc.object();
                bool locked = jsonObj["locked"].toBool();
                QString owner = jsonObj["nick_name"].toString();

                if (!locked) {
                    // 控制权为自己所有
                    LOG_DEBUG("控制权为自己所有，无需抢占");
                    emit controlAuthorityUpdated(true, ""); // 发出控制权状态信号，有控制权
                } else {
                    // 控制权属于其他客户端
                    LOG_DEBUG("控制权属于其他客户端: {}", owner.toStdString());
                    emit controlAuthorityUpdated(false, owner); // 发出控制权状态信号，无控制权
                }
            } else {
                emit controlAuthorityUpdated(false, ""); // 发出控制权状态信号
            }

            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 抢占控制权
 * @param nickName 客户端昵称
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求抢占机器人的控制权。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送抢占控制权命令，并通过回调函数处理响应结果。
 */
void RobotController::acquireControlAuthority(const QString& nickName, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("抢占控制权失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 构造请求JSON
    QJsonObject obj;
    obj["nick_name"] = nickName;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
    
    // 记录日志
    LOG_INFO("执行抢占控制权操作 - 命令ID: {}, 昵称: {}", cmdId, nickName.toStdString());
    
    // 发送抢占控制权请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_confSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            emit operationCompleted(CMD_GET_CONTROL_AUTHORITY, success);
            LOG_INFO("抢占控制权完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 释放控制权
 * @param cmdId 命令ID，用于标识本次请求
 * 
 * 该函数通过发送请求释放机器人的控制权。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送释放控制权命令，并通过回调函数处理响应结果。
 */
void RobotController::releaseControlAuthority(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("释放控制权失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }
    
    // 记录日志
    LOG_INFO("执行释放控制权操作 - 命令ID: {}", cmdId);
    
    // 发送释放控制权请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_confSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("释放控制权完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 重定位操作
 * @param isAuto 是否自动重定位
 * @param x X坐标
 * @param y Y坐标
 * @param angle 角度
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求执行机器人的重定位操作。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送重定位命令，并通过回调函数处理响应结果。
 */
void RobotController::reposition(bool isAuto, double x, double y, double angle, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("重定位操作失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 构造请求JSON
    QJsonObject obj;
    obj["isAuto"] = isAuto;
    obj["x"] = x;
    obj["y"] = y;
    obj["angle"] = angle;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 记录日志
    LOG_INFO("执行重定位操作 - 命令ID: {}, isAuto: {}, x: {}, y: {}, angle: {}",
                       cmdId, isAuto, x, y, angle);

    // 发送重定位请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_ctrlSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("重定位操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 控制机器人开环运动
 * @param vx X轴速度
 * @param vy Y轴速度
 * @param rad 旋转速度
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求控制机器人的开环运动。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送开环运动命令，并通过回调函数处理响应结果。
 */
void RobotController::startLoopMoveRobot(double vx, double vy,double rad, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人开环运动控制失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 构造请求JSON
    QJsonObject obj;
    obj["vx"] = vx;
    obj["vy"] = vy;
    obj["w"] = rad;
    QJsonDocument doc(obj);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);

    // 记录日志
    LOG_INFO("执行机器人开环运动控制 - 命令ID: {}, Vx: {}, Vy: {} rad: {}", cmdId, vx, vy, rad);

    // 发送开环运动控制请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_ctrlSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("机器人开环运动控制完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 停止机器人开环运动
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求停止机器人的开环运动。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送停止命令，并通过回调函数处理响应结果。
 */
void RobotController::stopLoopMoveRobot(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("停止机器人开环运动失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行停止机器人开环运动 - 命令ID: {}", cmdId);

    // 发送停止开环运动请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_ctrlSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("停止机器人开环运动完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 获取当前地图中的站点信息
 * 
 * 该函数用于向机器人发送请求，获取当前地图中所有站点的信息。
 * 函数会检查机器人连接状态，记录操作日志，并通过回调函数处理响应结果。
 * 
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::getMapSiteInformation(int cmdId){
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行获取当前地图中站点信息 - 命令ID: {}", cmdId);

    // 发送获取当前地图中站点信息请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("获取当前地图中站点信息完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 执行指定路径导航操作
 * 
 * 该函数通过导航套接字向机器人发送路径导航指令，用于控制机器人按照指定路径移动。
 * 函数会检查机器人连接状态，记录操作日志，并通过回调函数处理响应结果。
 * 
 * @param pathData 包含路径信息的JSON格式字符串
 * @param cmdId 命令ID，用于标识和匹配请求响应
 */
void RobotController::executePathNavigation(const QString& pathData, int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("执行指定路径导航失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行指定路径导航 - 命令ID: {}", cmdId);

    // 将QString转换为QByteArray
    QByteArray jsonData = pathData.toUtf8();

    // 发送指定路径导航请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("指定路径导航完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            if(success){
                emit robotStatus("任务已发送！客户端接收成功!");
            }else{
                emit robotStatus("任务已发送!但客户端返回错误信息！");
            }
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 执行通用命令接口
 * @param cmdId 命令ID，用于标识和匹配请求响应
 * @param jsonData 命令数据，包含具体命令信息的JSON格式数据
 * @param socketType socket类型，用于指定使用哪个socket发送命令:
 *        0 - m_naviSocket (默认:导航套接字)
 *        1 - m_ctrlSocket  (控制套接字)
 *        2 - m_statSocket  (状态查询套接字)
 *        3 - m_otherSocket (软急停套接字)
 *        4 - m_confSocket  (配置套接字)
 *        5 - m_logsSocket  (日志下载套接字)
 * 
 * 该函数提供了一个通用接口，用于发送任意命令到机器人控制器。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送命令，并通过回调函数处理响应结果。
 */
void RobotController::executeGenericCommand(int cmdId, const QByteArray& jsonData,int socketType) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("执行通用命令失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行通用命令 - 命令ID: {}, Socket类型: {}", cmdId, socketType);

    // 根据socketType选择对应的socket
    SCStatusTcp* targetSocket = nullptr;
    switch(socketType) {
        case 1:
            targetSocket = &m_ctrlSocket;
            break;
        case 2:
            targetSocket = &m_statSocket;
            break;
        case 3:
            targetSocket = &m_otherSocket;
            break;
        case 4:
            targetSocket = &m_confSocket;
            break;
        case 5:
            targetSocket = &m_logsSocket;
            break;
        case 0:
        default:
            targetSocket = &m_naviSocket;
            break;
    }

    // 发送通用命令请求，并设置回调函数处理响应
    m_requestManager.sendRequest(targetSocket, cmdId, jsonData,
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("通用命令执行完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            if(success){
                emit robotStatus("任务已发送！客户端接收成功!");
            }else{
                emit robotStatus("任务已发送!但客户端返回错误信息！");
            }
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 重定位成功后执行指定路径导航
 * @param pathData 路径数据，包含导航路径信息
 * @param relocateCmdId 重定位命令ID，用于标识重定位操作
 * @param navigateCmdId 导航命令ID，用于标识导航操作
 * 
 * 该函数首先执行重定位操作，当重定位成功后再执行路径导航。
 * 通过监听operationCompleted信号来判断重定位是否完成，并根据结果决定是否执行导航。
 */
void RobotController::relocateAndNavigate(const QString& pathData, int relocateCmdId, int navigateCmdId) {
    // 先执行重定位
    relocation(relocateCmdId);
    
    // 监听重定位完成信号
    connect(this, &RobotController::operationCompleted, this, [this, pathData, relocateCmdId, navigateCmdId](int cmdId, bool success) {
        LOG_INFO("Relocation completed:cmdId：{} relocateCmdId:{} 执行路径导航!",relocateCmdId);
        if (cmdId == relocateCmdId && success) {
            LOG_INFO("Relocation completed:{} 执行路径导航!",relocateCmdId);
            // 重定位成功后执行路径导航
            executePathNavigation(pathData, navigateCmdId);
            // 断开连接以避免重复执行
            disconnect(this, &RobotController::operationCompleted, nullptr, nullptr);
        } else if (cmdId == relocateCmdId && !success) {
            // 重定位失败，发出错误信号
            emit robotStatus("重定位失败,无法进行导航任务!");
            disconnect(this, &RobotController::operationCompleted, nullptr, nullptr);
        }
    });
}

/**
 * @brief 查询机器人报警状态
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求查询机器人的报警状态信息。
 * 首先检查与机器人的连接状态，如果未连接则直接返回。
 * 通过请求管理器发送查询报警状态命令，并通过回调函数处理响应结果。
 */
void RobotController::getRobotAlarmStatus(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("查询机器人报警状态失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行查询机器人报警状态 - 命令ID: {}", cmdId);

    // 发送查询机器人报警状态请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("查询机器人报警状态完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 查询任意两点之间的路径
 * @param cmdId 命令ID，用于标识本次请求
 *
 * 该函数通过发送请求获取所有可用地图的列表。
 */
void RobotController::getPathBetweenTwoPoint(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("查询任意两点之间的路径: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("查询任意两点之间的路径 - 命令ID: {}", cmdId);

    // 发送获取地图列表请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_statSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("查询任意两点之间的路径 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 清除机器人当前所有报错
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::clearRobotAlarms(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("清除机器人报警失败: 机器人未连接");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行清除机器人当前所有报错 - 命令ID: {}", cmdId);

    // 发送清除机器人报警请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_confSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("清除机器人当前所有报错完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 暂停导航操作
 * 
 * 该函数用于向机器人发送暂停导航指令。
 * 函数会检查机器人连接状态，记录操作日志，并通过回调函数处理响应结果。
 * 
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::pauseNavigation(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行暂停导航操作 - 命令ID: {}", cmdId);

    // 发送暂停导航请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("暂停导航操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            if(success){
                emit robotStatus("暂停导航操作成功!");
            }else{
                emit robotStatus("暂停导航操作失败!");
            }
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 恢复导航操作
 * 
 * 该函数用于向机器人发送恢复导航指令。
 * 函数会检查机器人连接状态，记录操作日志，并通过回调函数处理响应结果。
 * 
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::resumeNavigation(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行恢复导航操作 - 命令ID: {}", cmdId);

    // 发送恢复导航请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("恢复导航操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            if(success){
                emit robotStatus("恢复导航操作成功!");
            }else{
                emit robotStatus("恢复导航操作失败!");
            }
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 取消导航操作
 * 
 * 该函数用于向机器人发送取消导航指令。
 * 函数会检查机器人连接状态，记录操作日志，并通过回调函数处理响应结果。
 * 
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::cancelNavigation(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行取消导航操作 - 命令ID: {}", cmdId);

    // 发送取消导航请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_naviSocket, cmdId, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("取消导航操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            if(success){
                emit robotStatus("取消导航操作成功!");
            }else{
                emit robotStatus("取消导航操作失败!");
            }
            //handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 下载日志文件压缩包
 * @param cmdId 命令ID
 */
void RobotController::downloadLogFiles(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行日志文件下载操作 - 命令ID: {}", cmdId);

    // 发送日志文件下载请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_logsSocket, RMS_CLIENT_CMD_LOG_DOWNLOAD, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("日志文件下载操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");
            
            if (success) {
                // 创建日志目录
                QString logsDirPath = QString("data/%1/logs").arg(m_robotId);
                QDir logsDir(logsDirPath);
                if (!logsDir.exists()) {
                    if (logsDir.mkpath(".")) {
                        LOG_DEBUG("创建日志目录成功 - 路径: {}", logsDirPath.toStdString());
                    } else {
                        LOG_WARN("创建日志目录失败 - 路径: {}", logsDirPath.toStdString());
                        emit robotStatus("创建日志目录失败!");
                        return;
                    }
                }
                
                // 保存压缩包文件 (使用tar.gz格式)
                QString tarGzFilePath = QString("%1/log_files_%2.tar.gz").arg(logsDirPath).arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"));
                QFile tarGzFile(tarGzFilePath);
                if (tarGzFile.open(QIODevice::WriteOnly)) {
                    tarGzFile.write(resp);
                    tarGzFile.close();
                    LOG_INFO("日志压缩包保存成功 - 路径: {}", tarGzFilePath.toStdString());
                    
                    // 解压tar.gz文件
                    QString extractCommand = QString("tar -xzf \"%1\" -C \"%2\" --strip-components=1").arg(tarGzFilePath).arg(logsDirPath);
                    int result = system(extractCommand.toStdString().c_str());
                    if (result == 0) {
                        LOG_INFO("日志文件解压成功 - 路径: {}", logsDirPath.toStdString());
                        emit robotStatus("日志文件下载并解压成功!");
                        // 解压成功后删除压缩文件以节省存储空间
                        QFile::remove(tarGzFilePath);
                        LOG_INFO("日志压缩包已删除 - 路径: {}", tarGzFilePath.toStdString());
                    } else {
                        LOG_ERROR("日志文件解压失败 - 命令: {}", extractCommand.toStdString());
                        emit robotStatus("日志文件解压失败!");
                    }
                } else {
                    LOG_ERROR("无法保存日志压缩包 - 路径: {}", tarGzFilePath.toStdString());
                    emit robotStatus("日志文件保存失败!");
                }
            } else {
                emit robotStatus("日志文件下载失败!");
            }
            handleOperationCompleted(cmdId, success, resp);
        }
    );
}

/**
 * @brief 清理客户端日志文件
 * 
 * 向机器人发送日志文件清理请求，并处理响应结果。
 * 此功能用于远程清理机器人上的日志文件以释放存储空间。
 * 
 * @param cmdId 命令ID，用于标识本次操作的唯一ID
 */
void RobotController::cleanClientLogFiles(int cmdId) {
    // 检查连接状态
    if (!isConnected()) {
        LOG_WARN("机器人未连接!");
        emit robotStatus("robot not connected!");
        return;
    }

    // 记录日志
    LOG_INFO("执行日志文件清理操作 - 命令ID: {}", cmdId);

    // 发送日志文件清理请求，并设置回调函数处理响应
    m_requestManager.sendRequest(&m_logsSocket, RMS_CLIENT_CMD_LOG_FILE_CLEAN, QByteArray(),
        [this, cmdId](const QByteArray &resp) {
            bool success = !resp.isEmpty();
            LOG_INFO("日志文件清理操作完成 - 命令ID: {}, 结果: {}", cmdId, success ? "成功" : "失败");

            // 处理响应结果
            if (success) {
                // 解析返回的JSON数据
                QJsonDocument jsonResponse = QJsonDocument::fromJson(resp);
                if (jsonResponse.isNull() || !jsonResponse.isObject()) {
                    LOG_ERROR("日志文件清理操作返回无效JSON数据");
                    emit robotStatus("日志文件清理操作返回无效数据!");
                    handleOperationCompleted(cmdId, false, resp);
                    return;
                }

                QJsonObject responseJson = jsonResponse.object();
                QString infoMsg = responseJson.value("info_msg").toString();
                int retCode = responseJson.value("ret_code").toInt(-1);

                // 根据返回码判断操作是否成功
                if (retCode == 0) {
                    LOG_INFO("日志文件清理成功 - 信息: {}", infoMsg.toStdString());
                    emit robotStatus(QString("日志文件清理成功: %1").arg(infoMsg));
                } else {
                    LOG_WARN("日志文件清理失败 - 错误: {}", infoMsg.toStdString());
                    emit robotStatus(QString("日志文件清理失败: %1").arg(infoMsg));
                }

                handleOperationCompleted(cmdId, retCode == 0, resp);
            } else {
                emit robotStatus("日志文件清理失败!");
            }
        }
    );
}
